import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { getCurrentContext, getCurrentTraceId, getCurrentUri } from '@/common/async-context';

export interface AutoContext {
    traceId: string;
    uri: string;
}

/**
 * 自动上下文装饰器
 * 在服务方法中自动获取当前请求的上下文信息
 * 使用方式：@AutoContext() context: AutoContext
 */
export const AutoContext = createParamDecorator((data: unknown, ctx: ExecutionContext): AutoContext => {
    // 如果在HTTP请求上下文中，尝试从ExecutionContext获取
    if (ctx.getType() === 'http') {
        const request = ctx.switchToHttp().getRequest();
        if (request.traceId && request.uri) {
            return {
                traceId: request.traceId,
                uri: request.uri,
            };
        }
    }

    // 否则从AsyncLocalStorage获取
    const context = getCurrentContext();
    return (
        context || {
            traceId: 'unknown',
            uri: 'unknown',
        }
    );
});

/**
 * 自动TraceId装饰器
 * 在服务方法中自动获取当前请求的traceId
 * 使用方式：@AutoTraceId() traceId: string
 */
export const AutoTraceId = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    // 如果在HTTP请求上下文中，尝试从ExecutionContext获取
    if (ctx.getType() === 'http') {
        const request = ctx.switchToHttp().getRequest();
        if (request.traceId) {
            return request.traceId;
        }
    }

    // 否则从AsyncLocalStorage获取
    return getCurrentTraceId();
});

/**
 * 自动URI装饰器
 * 在服务方法中自动获取当前请求的URI
 * 使用方式：@AutoUri() uri: string
 */
export const AutoUri = createParamDecorator((data: unknown, ctx: ExecutionContext): string => {
    // 如果在HTTP请求上下文中，尝试从ExecutionContext获取
    if (ctx.getType() === 'http') {
        const request = ctx.switchToHttp().getRequest();
        if (request.uri) {
            return request.uri;
        }
    }

    // 否则从AsyncLocalStorage获取
    return getCurrentUri();
});
